<!--

    Copyright 2006-2019 the original author or authors.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

-->
<html>
<head>
    <title>The Details</title>
</head>
<body>

<p>The <a href="tutorial.html">Tutorial</a> allows you to perfectly use Objenesis.
However, if you want implementation details, tools and more power, you're at
the right place.</p>

<h1 id="testYourEnvironment">Test your environment</h1>

<p>Depending on your JVM and security manager, Objenesis might not be able to
instantiate some of your classes. If that's the case, first, we are highly
interested in <a href="support.html">knowing this limitation</a>.</p>

<p>Then, to prevent this, we provide a TCK to run in your environment. You can
find it on our <a href="download.html">download page</a>. It will print a report
to the standard output. Exceptions, if they occur, will be printed out to
the standard error. Tests are run against <a href="${javadoc}/org/objenesis/ObjenesisStd.html">ObjenesisStd</a>
and <a href="${javadoc}/org/objenesis/ObjenesisSerializer.html">ObjenesisSerializer</a>
and are made of every kind of class types you might want to instantiate. So you can check if all
of them or at least the kind you want are correctly instantiated.</p>

<p>To launch from the command line, just type</p>

<pre>java -jar objenesis-${project.version}-tck.jar</pre>

<p>Note that the Objenesis jar is bundled in the TCK so no special classpath is needed.</p>

<p>To launch from within an application server, the easiest is to bundle it in your application
and to call <code>org.objenesis.tck.Main.main()</code> from your code.</p>

<h2>Android</h2>

<p>Objenesis also works on Dalvik, the Android VM. So a TCK is also provided for it in the form of an apk. You
can also find it on <a href="download.html">download page</a>. Just use the following command to install and run
it.</p>

<pre>
adb install -r objenesis-tck-android-${project.version}.apk
adb shell am instrument -w org.objenesis.tck.android/.TckInstrumentation
</pre>

<h1>Exception Handling</h1>

<p>If something wrong occurs using Objenesis, you will normally get an
<a href="${javadoc}/org/objenesis/ObjenesisException.html">ObjenesisException</a>
wrapping the real exception. It is a RuntimeException so you don't have to
catch it. Some reasons why it fails:</p>

<ul>
    <li>Using ObjenesisSerializer with a class that isn't <code>Serializable</code>.</li>
    <li>Using ObjenesisSerializer, the constructor of the first parent class that isn't
        <code>Serializable</code> throws an exception.</li>
    <li>Your SecurityManager prevents Objenesis from working normally.</li>
    <li>Objenesis isn't able to work for some reason. Please <a href="support.html">tell us</a></li>
</ul>

<h1>ObjectInstantiator caching</h1>

<p><a href="${javadoc}/org/objenesis/ObjenesisBase.html">ObjenesisBase</a> provides a built-in cache
that is activated by default. This cache keeps <a href="${javadoc}/org/objenesis/instantiator/ObjectInstantiator.html">
ObjectInstantiator</a> instances per Class. This improves performance quite a lot when the same Class
is frequently instantiated. For this reason, it is recommended to reuse Objenesis instances whenever
possibly or to keep is as a singleton in your favorite dependency injection framework.</p>

<p>However, you can always disable the cache if needed.</p>
<pre>
    Objenesis o = new ObjenesisStd(false); // cache disabled
</pre>

<p>The cache should behave correctly in an application server and not cause any memory leaks.</p>

<h1>Use you own strategy</h1>

<p>As you've seen in the <a href="tutorial.html">Tutorial</a>, Objenesis implementations
are determining the best instantiator using a strategy. It might occurs that you need
to implement your own strategy. Two possible reasons I can think of are that</p>

<ul>
   <li><strong>You want to specialize for a given JVM.</strong> Default strategies are
       supporting all JVMs. This has a little performance cost so you might want to
       provide a strategy that is optimized for your JVM.
<pre>
public class Sun14Strategy implements InstantiatorStrategy {
    public ObjectInstantiator newInstantiatorOf(Class type) {
        // return sun dedicated instantiator
        return new SunReflectionFactoryInstantiator(type);
    }
}
</pre></li>
    <li><strong>Objenesis doesn't support your environment by default.</strong> In that
        case, we would be really happy to add this support in our next version and
        meanwhile, you can use your own strategy and instantiator to fix this.</li>
</ul>

<p>From there, you can use this new strategy.</p>
<pre>
// Directly
Objenesis o = new ObjenesisBase(new Sun14Strategy());

// Or inside your Objenesis own implementation
public class ObjenesisSun14 extends ObjenesisBase {
    public ObjenesisSun14() {
       super(new Sun14Strategy());
    }
}
</pre>

<p>Also, if Objenesis can't find the right instantiator to use by itself, this doesn't mean it doesn't bundle
an instantiator that works on your platform. To try to find one, we provide a nice tool that will run through
all the instantiators and tell you which ones work</p>

<pre>java -cp objenesis-${project.version}-tck.jar org.objenesis.tck.search.SearchWorkingInstantiator</pre>

<p>Some culprits:</p>
<ul>
    <li>Some instantiators are made to mimic the Java serialization. It means they will call the default constructor of the first non-serializable class</li>
    <li>Some instantiators only works if the class is serializable</li>
    <li>Some instantiators will in fact call the default constructor</li>
    <li>Depending on your security manager, classes coming from a low level class loader might not be instantiable</li>
</ul>

<h1>The Evil ObjenesisHelper</h1>

<p>Static methods are considered a really bad practice. They can't be mocked or
replace easily. Worst, if the class keep a static state, you will fell in
class loading issues, memory leaks, module dependencies and so on. <strong>We
strongly recommend you not to use them.</strong></p>

<p>However, if for some reason that we prefer ignore, you still want to use Objenesis
in a static way, you can do so. It's called <a href="${javadoc}/org/objenesis/ObjenesisHelper.html">ObjenesisHelper</a>.</p>

<p>We prefer to provide it knowing that some of you will code it anyway. It a wrapper
over an <a href="${javadoc}/org/objenesis/ObjenesisStd.html">ObjenesisStd</a>
and <a href="${javadoc}/org/objenesis/ObjenesisSerializer.html">ObjenesisSerializer</a>
instance which are kept statically.</p>

<p>It can't be more straightforward to use:</p>

<pre>
   Object o1 = ObjenesisHelper.newInstance(MyClass.class);
   Object o2 = ObjenesisHelper.newSerializableInstance(MyClass.class);
   ObjectInstantiator o3 = ObjenesisHelper.getInstantiatorOf(MyClass.class);
   ObjectInstantiator o4 = ObjenesisHelper.getSerializableObjectInstantiatorOf(MyClass.class);
</pre>

<h1>Serializing instantiator details</h1>

<p>The instantiator returned by <code>SerializingInstantiatorStrategy</code> will do the following.</p>

<ul>
  <li>Fail is the class is not serializable</li>
  <li>Call the no-arg constructor of the first none serializable class. Just like the serialization would do</li>
  <li><code>Externalizable</code> classes won't have a special treatment. If you want one, implement it yourself</li>
  <li>No serializable specific method is called (e.g. <code>readResolve, readExternal, readObject, readObjectNoData</code>)</li>
</ul>

</body>
</html>
